<?php
/**
 * Created by PhpStorm.
 * User: yangfan
 * Date: 2020/1/17
 * Time: 3:36 PM
 */

namespace App\BO\PaymentState;

use App\BO\OrderStatus\OrderStatus;
use App\BO\Wechat\Meta\NoPayRefundMeta;
use App\BO\Wechat\WechatOperationProxy;
use App\Entities\GoodsPaymentEntity;
use App\Entities\OrderEntity;
use App\Entities\OrderModel;
use App\Entities\OrderRefundEntity;
use App\Entities\PaymentEntity;

use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;

trait PaymentOperationTrait
{
    /**
     * @param PaymentEntity $paymentEntity
     * @param GoodsPaymentEntity $goodsPaymentEntity
     * @throws \Exception
     */
    private function toRefundThirdPartConfirmSuccess(PaymentEntity $paymentEntity, GoodsPaymentEntity $goodsPaymentEntity)
    {
        DB::beginTransaction();

        // 1. 修改 payment 记录
        $paymentEntity->setState(PaymentStateDefinition::STATE_REFUND_SUCCESS);
        $paymentEntity->save();

        if ($goodsPaymentEntity->getIsMaster()) {  // 如果是主订单
            $order = OrderEntity::find($goodsPaymentEntity->getOrderId());
            $orderStatus = new OrderStatus($order);
            $orderStatus->getOrderStateContext()->refund();
        }
        DB::commit();
    }

    /**
     * 退款动作
     * @param PaymentEntity $paymentEntity
     * @param GoodsPaymentEntity $goodsPaymentEntity
     * @throws \Exception
     */
    protected function refundOperation(PaymentEntity $paymentEntity, GoodsPaymentEntity $goodsPaymentEntity)
    {
        if ($paymentEntity->getPaymentMethod() == OrderModel::PAYMENT_METHOD_LJSH) {  // 如果是模拟支付的
            $this->toRefundSuccess($paymentEntity, $goodsPaymentEntity);
            Log::info("paymentId = {$paymentEntity->getId()} :无需请求第三方接口：退款成功");
        } else {
            // 真实微信退款，将状态设置为等待第三方通知
            $this->toRefundWaitingThirdPartNotify($paymentEntity, $goodsPaymentEntity);
            Log::info("paymentId = {$paymentEntity->getId()} :第三方退款申请提交成功");
        }
    }

    /**
     * 设置为退款成功
     * @param PaymentEntity $paymentEntity
     * @param GoodsPaymentEntity $goodsPaymentEntity
     * @throws \Exception
     */
    private function toRefundSuccess(PaymentEntity $paymentEntity, GoodsPaymentEntity $goodsPaymentEntity)
    {
        $ret = new NoPayRefundMeta();

        DB::beginTransaction();

        // 1. 修改 payment 记录
        $paymentEntity->setOutRefundTradeNo($ret->getRefundId());
        $paymentEntity->setState(PaymentStateDefinition::STATE_REFUND_SUCCESS);
        $paymentEntity->setRefundAt($ret->getRefundAt());
        $paymentEntity->save();

        if ($goodsPaymentEntity->getIsMaster()) {  // 如果是主订单
            // 1. 修改 order_refund 表
            $orderRefundEntity = OrderRefundEntity::findByOrderId($goodsPaymentEntity->getOrderId());
            $orderRefundEntity->setOutRefundNo($ret->getRefundId());
            $orderRefundEntity->setRefundAt($ret->getRefundAt());
            $orderRefundEntity->save();

            // 2. 改变订单状态
            $order = OrderEntity::find($goodsPaymentEntity->getOrderId());
            $orderStatus = new OrderStatus($order);
            $orderStatus->getOrderStateContext()->refund();
        }

        DB::commit();
    }

    /**
     * 设置为等待第三方回调确认
     * @param PaymentEntity $paymentEntity
     * @param GoodsPaymentEntity $goodsPaymentEntity
     * @throws \Exception
     */
    private function toRefundWaitingThirdPartNotify(PaymentEntity $paymentEntity, GoodsPaymentEntity $goodsPaymentEntity)
    {
        $ret = WechatOperationProxy::refund($paymentEntity);

        DB::beginTransaction();

        // 1. 修改 payment 记录
        $paymentEntity->setOutRefundTradeNo($ret->getRefundId());
        $paymentEntity->setState(PaymentStateDefinition::STATE_REFUND_WAITING_THIRD_PART_NOTIFY);
        $paymentEntity->setRefundAt($ret->getRefundAt());
        $paymentEntity->save();

        if ($goodsPaymentEntity->getIsMaster()) {  // 如果是主订单
            // 1. 修改 order_refund 表
            $orderRefundEntity = OrderRefundEntity::findByOrderId($goodsPaymentEntity->getOrderId());
            $orderRefundEntity->setOutRefundNo($ret->getRefundId());
            $orderRefundEntity->setRefundAt($ret->getRefundAt());
            $orderRefundEntity->save();

            // 改变订单状态
            $order = OrderEntity::find($goodsPaymentEntity->getOrderId());
            $orderStatus = new OrderStatus($order);
            $orderStatus->getOrderStateContext()->applyThirdPartRefund();
        }

        DB::commit();
    }
}
